﻿//Copyright (c) 2008 Michael J. Ryan & Apollo Group, Inc.

//Permission is hereby granted, free of charge, to any person
//obtaining a copy of this software and associated documentation
//files (the "Software"), to deal in the Software without
//restriction, including without limitation the rights to use,
//copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the
//Software is furnished to do so, subject to the following
//conditions:

//The above copyright notice and this permission notice shall be
//included in all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;
using System.Net;
using System.Threading;
using Apollo.Common.Configuration;

//TODO: Add logging to new functionality...

//NOTE: uses internal LogTool, not Apollo.Common.Logging.LogTool

/****************************************************************************************
Apollo.Common...Configuration will retreive values based on the 
Applications .config file, with the following settings in ApplicationSettings...
	acc-application-name	name of the application
	acc-application-ver	application version
	acc-enviroment		mirrors Apollo.Common.Configuration.Core.Environment
						LOCAL, DEVELOPMENT, QA, or PRODUCTION
	acc-endpoint		endpoint for the settings lookup

The following values will be transposed.
	{env}	LOCAL, DEVELOPMENT, QA, PRODUCTION
	{app}	Name of the application the setting is for
	{ver}	Application Version
	{cfg}	Name of the setting in question.

The following types of endpoints can be used (examples)
	C:\configs\{cfg}.{env}.{app}.{ver}.config
	\\SERVERNAME\SHARENAME\{env}.{app}.{ver}.{cfg}.config

The application name, version, and cfg/setting values will be lowercased, and spaces will be replaced with an 
underscore '_'

The attempts to retrieve resources will happen, in the following order.
	env + app + ver + cfg
	env + app + cfg
	env + cfg
	cfg

The resource path will replace 2+ periods, with one period, to aid in local configuration files.
ex:
	C:\configs\LOCAL.portal.4.2.1.memcached.config
	C:\configs\LOCAL.portal..memcached.config >>  C:\configs\LOCAL.portal.memcached.config
	C:\configs\LOCAL...memcached.config >>  C:\configs\LOCAL.memcached.config

****************************************************************************************/

namespace Apollo.Common.Configuration
{
	/// <summary>
	/// Class to retrieve configuration values from a common endpoint.
	/// </summary>
	public static class Config
	{
		private const string AppStateName = "Apollo.Common.Configuration.Cache";
	
#region Constructors
		/// <summary>
		/// Static ctor for the Apollo.Common.Configuration Config class.
		/// </summary>
		static Config()
		{
			//static default for desktop apps..
			_configurationCache = new ConfigurationCache();
		}
#endregion

#region Public Static Methods
	#region Get
		public static ConfigurationSet Get(string settingName)
		{
			ConfigurationFile f = ConfigurationCache.GetConfigurationFile(settingName);
			
			if (f != null)
				return f.ConfigurationSet;
				
			return ConfigurationSet.Empty;
		}
	#endregion

	#region Read
		public static string Read(string settingName)
		{
			ConfigurationFile f = ConfigurationCache.GetConfigurationFile(settingName);
			
			if (f != null)
				return f.Text;
				
			return String.Empty;
		}
	#endregion
	
	#region GetFile
		public static ConfigurationFile GetFile(string settingName)
		{
			return ConfigurationCache.GetConfigurationFile(settingName);
		}
	#endregion
#endregion

#region Private Static Properties

	#region ConfigCache
		private static object _hnd = new object();
		private static readonly ConfigurationCache _configurationCache;
		private static ConfigurationCache ConfigurationCache
		{
			get {
				if (HttpContext.Current != null) {
					//web app -- reference against the web Application collection.
					ConfigurationCache ret = HttpContext.Current.Application[AppStateName] as ConfigurationCache;
					
					if (ret == null) {
						HttpContext.Current.Application.Lock();
						
						ret = HttpContext.Current.Application[AppStateName] as ConfigurationCache;
						if (ret == null) {
							ret = new ConfigurationCache();
							HttpContext.Current.Application.Add(AppStateName, ret);
						}
						
						HttpContext.Current.Application.UnLock();
					}
					
					return ret;
					
				} else {
					//desktop app - use single cache item.
					return _configurationCache;
				}
			}
		}
	#endregion

#endregion

	}
}
